package com.knightcloud.micro.auth.config.security.jackson;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.MissingNode;
import com.knightcloud.micro.auth.config.security.LoginUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import java.io.IOException;
import java.time.LocalDate;
import java.util.Set;

/**
 * LoginUser 反序列化
 *
 * @author knight
 */
public class LoginUserDeserializer extends JsonDeserializer<LoginUser> {

	private static final TypeReference<Set<SimpleGrantedAuthority>> SIMPLE_GRANTED_AUTHORITY_SET = new TypeReference<>() {
	};

	@Override
	public LoginUser deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
		ObjectMapper mapper = (ObjectMapper) jp.getCodec();
		JsonNode jsonNode = mapper.readTree(jp);
		Set<? extends GrantedAuthority> authorities = mapper.convertValue(jsonNode.get("authorities"),
				SIMPLE_GRANTED_AUTHORITY_SET);
		JsonNode passwordNode = readJsonNode(jsonNode, "password");
		String id = readJsonNode(jsonNode, "id").asText();
		String username = readJsonNode(jsonNode, "username").asText();
		String password = passwordNode.asText("");
		String avatar = readJsonNode(jsonNode, "avatar").asText();
		String phone = readJsonNode(jsonNode, "phone").asText();
		String email = readJsonNode(jsonNode, "email").asText();
		Integer gender = readJsonNode(jsonNode, "gender").asInt();
		LocalDate birth = mapper.convertValue(readJsonNode(jsonNode, "birth").asText("1990-01-01"), LocalDate.class);
		boolean enabled = readJsonNode(jsonNode, "enabled").asBoolean();
		boolean accountNonExpired = readJsonNode(jsonNode, "accountNonExpired").asBoolean();
		boolean accountNonLocked = readJsonNode(jsonNode, "accountNonLocked").asBoolean();
		boolean credentialsNonExpired = readJsonNode(jsonNode, "credentialsNonExpired").asBoolean();

		LoginUser result = new LoginUser(id, username, password, avatar, phone, email, gender, birth, authorities,
				enabled, accountNonExpired, accountNonLocked, credentialsNonExpired);
		if (passwordNode.asText(null) == null) {
			result.eraseCredentials();
		}
		return result;
	}

	private JsonNode readJsonNode(JsonNode jsonNode, String field) {
		return jsonNode.has(field) ? jsonNode.get(field) : MissingNode.getInstance();
	}

}
